package Main;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Pattern;

import model.ListeDeNoeudsEval;
import model.Noeud;
import model.ParseXML;
import webSemantique.Ontology;

public class Recherche {
	private ListeDeNoeudsEval ln;
	private String stopListePath = "./stopliste.txt";
	private String qRelsPath = "./Qrels/qrel";
	private String requete;
	private List<String> motClefs;
	private HashSet<String> hashStopListe;
	private boolean useSemantique = false;
	private Ontology ontology;
	private List<Noeud> resultat;
	private boolean useReasoner = false; 
	
	private static Mysql bdd;
	
	public Recherche( )
	{
		bdd = Mysql.getInstance();
		ln = ListeDeNoeudsEval.getInstance();
		hashStopListe = new HashSet<String>();
		
		initStopListe();
		
		boolean continuer = true;
		while(continuer)
		{
			continuer = demanderRequete();
			if(continuer)
			{
				setSemantique();
				
				System.out.println("Analyse...");
				for(int i = 3 ; i >= 1 ; i--)
					analyser(i);
				
				afficherResultat();
				calculPertinence();
			}
		}
		
	}
	
	private void afficherResultat() {
		if(resultat.isEmpty())
            System.out.println("Aucun résultat.");
		else
		{
			//for (int i=resultat.size()-1;i>=Math.max(0, resultat.size()-25);i--) {
			for (int i=0; i<resultat.size() ; i++) {
				System.out.println(resultat.get(i) + " | evaluation : " + resultat.get(i).getEval());
			}
		}
	}

	private void calculPertinence() {
		if(resultat != null && !resultat.isEmpty())
		{
			System.out.print("Qrel associée ? ");
			Scanner scan = new Scanner(System.in);
			String numQrel = scan.nextLine();
			
			if(!numQrel.equals("."))
			{
				String qrel = qRelsPath + numQrel + ".txt";
				FileInputStream ips;
				int pertinence5 = 0;
				int pertinence10 = 0;
				int pertinence25 = 0;
				
				try {
					
					ips = new FileInputStream(qrel);
					InputStreamReader ipsr=new InputStreamReader(ips);
					BufferedReader br =new BufferedReader(ipsr);
					System.out.println("--> " + qrel + " chargée");
					
					String ligne;
					ArrayList<String> qrelPertinents = new ArrayList<String>();

					while ((ligne=br.readLine())!=null){
						String result[] = ligne.split("\t");
						if(result[2].trim().equals("1"))
							qrelPertinents.add(new String(result[0].trim()+ " "+result[1].trim()));
					}
					
					int nbPertinent = 0;
					
					for(int i = 0 ; i< resultat.size() ; i++)
					{
						
						for(int j = 0 ; j< qrelPertinents.size() ; j++)
						{
							if(resultat.get(i).equals(qrelPertinents.get(j)))
								nbPertinent++;
						}
						
						if( i == 5 )
							pertinence5 = nbPertinent;
						else if( i == 10 )
							pertinence10 = nbPertinent;
						else if( i == 25 )
							pertinence25 = nbPertinent;						
					}
					
				} catch (FileNotFoundException e) {
					
					System.out.println("Erreur : Fichier Qrel introuvable");
				} catch (IOException e) {
					
					System.out.println("Erreur lors de la lecture du Qrel");
				}
				
				
				System.out.println("Pertinence à  5 : " + pertinence5);
				System.out.println("Pertinence à  10 : " + pertinence10);
				System.out.println("Pertinence à  25 : " + pertinence25);
			}
		}
		
	}

	private void setSemantique() {
      
		Scanner scan = new Scanner(System.in);
		
        boolean fin= false;
        
        while ( !fin)
        {
           System.out.print("Utiliser le semantique (O/N) ---->  ");
           String motcle = scan.nextLine();
           if(motcle.equals("O") || motcle.equals("o") )
           {
        	   	   useSemantique = true;   
                   ontology = new Ontology();
                   ontology.getAnnotations();
                   fin = true;
           }
           else if (motcle.equals("n") || motcle.equals("N"))
           {
                   useSemantique = false;
                   fin = true;
           }         
        }	
	}

	public void analyser(int groupeDeMot) {
		
		
		for(int i = 0 ; i <= motClefs.size() - groupeDeMot; i++)
		{
			String motCherche = "";
			for(int k = i ; k < groupeDeMot+i ; k++)
				motCherche = motCherche + " " + motClefs.get(k) ;
			
			if(!hashStopListe.contains(motCherche) && motCherche.length() > 1 ) 
			{
				if(useSemantique)
				{	            	            
		            Map<String,Double> listeEquivalent = ontology.getListeAChercher(motCherche.trim());
		           
		            for(int k = 0 ; k < listeEquivalent.size() ; k++){
		            	Object[] keys = listeEquivalent.keySet().toArray();
		            	boolean termeOk = rechercherUnTerme((String)keys[k], listeEquivalent.get(keys[k]) );
		            	
		            	// supprime les groupes de mots trouvés pour pas rechercher les mots seuls par la suite
		    		    for(int j =0 ; j < keys.length; j++)
		    		    {
		    		    	String[] split = ((String)keys[j]).split(" ");
		    		    	for(int z = 0 ; z < split.length ; z++)
		    		    			motClefs.remove(split[z]);
		    		    }
		            }
				}
				else{
					
					boolean termeOk = rechercherUnTerme(motCherche, 1.0);
				}
			}
		}

		resultat = getAndOrderResultats();
	}
	
	
	public boolean rechercherUnTerme (String terme, Double valeurTerme) {
		String[] termeSplit = terme.split(" ");
		boolean termeOk = false;
		if(termeSplit.length > 1 )
		{
			/* remplir dans le cas où l'étude porte sur un groupe de terme : ex "Mont blanc" */
			/* vérifier avant d'ajouter le resultat dans notre liste que le terme mont et le terme blanc sont bien côte 
			 *  à côté grâce à leurs positions.
			 *  Sinon cela considèrerait la phrase "le nuage au dessus du mont est blanc"
			 */
		}
		else
		{
			String req = "SELECT T.id " +
					 "FROM Termes T " +
					 "WHERE T.terme = '" + terme + "';";
			List<List> result = bdd.getResultSet (bdd.executeSelect(req));
			
			if (result.size() != 0) {
				int idTerme = Integer.parseInt((String) result.get(0).get(0));
				
				req = "SELECT N.id, N.nomBalise, N.ordre " +
						 "FROM Termes T, TermeNoeud TN, Noeuds N " +
						 "WHERE N.id = TN.idNoeud " +
						 "AND TN.idTerme = " + idTerme + " " +
						 "GROUP BY N.id;";
				
				ResultSet resultatRequete = bdd.executeSelect(req);
				result.clear();
				result = bdd.getResultSet(resultatRequete);
				
				for (int i=0;i<result.size();i++) {
					String balise = (String) result.get(i).get(1);
					int idNoeud, ordre;
					if (balise.equals("P") || balise.equals("p")) {	
						idNoeud = Integer.parseInt((String) result.get(i).get(0));
						ordre = Integer.parseInt((String) result.get(i).get(2));
						Noeud nd = new Noeud(idNoeud, balise, ordre);
						ln.insertElement(nd);
						ln.getElementById(idNoeud);
						nd.setVariables(idTerme, valeurTerme);
						
						termeOk = true;
					}
				}
			}
		}
		return termeOk;
	}
	

	
	public void pertinenceNoeud(Noeud nd) {
		
		double eval = 0.0;
		nd.setEval(eval);
		
	}

	public List<Noeud> getAndOrderResultats () {
		
		for (int i=0;i<ln.getListe().size();i++) {
			pertinenceNoeud(ln.getListe().get(i));
		}		
		
		List<Noeud> retour = new ArrayList<Noeud>();
		Object[] res = ln.getElementsTriesDecroissant();
		for (int i=0;i<res.length;i++) {
			retour.add((Noeud)res[i]);
		}
		return retour;
	}	
	
	public boolean demanderRequete()
	{
		System.out.print("Votre requète (\".\" pour quitter) : ");
		Scanner scan = new Scanner(System.in);
		requete = scan.nextLine();
		if(!requete.equals("."))
		{
			motClefs = new ArrayList<String>();
			requete = ParseXML.replaceSpecialChar(requete);
			requete = requete.toLowerCase();
	    	
			String REGEX = "[ 1234567890°{}$€%£*~@=^|#&§«»“”‹›<>„\"�…’'`_–,/.:;!?()\\-+*\n\t]+";
			Pattern pattern = Pattern.compile(REGEX);
		    String[] mots = pattern.split(requete);
		    for(int i =0 ; i < mots.length ; i++)
		    	motClefs.add(mots[i]);
		}
		else
			return false;
		
		return true;
		
	}
	
	private void initStopListe(){
		InputStream ips;
		try {
			
			ips = new FileInputStream(stopListePath);
			InputStreamReader ipsr=new InputStreamReader(ips);
			BufferedReader br =new BufferedReader(ipsr);
			String ligne;
			while ((ligne=br.readLine())!=null){
				hashStopListe.add(ligne);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
}
